package com.newasia.server.serviceImpl;

import com.newasia.server.common.exception.ExceptionUtil;
import com.newasia.server.common.exception.WeChatLoginException;
import com.newasia.server.common.checkHandler.*;
import com.newasia.server.common.result.ResponseData;
import com.newasia.server.common.tool.CheckObjectIsNullUtils;
import com.newasia.server.common.tool.CodePhoneUtils;
import com.newasia.server.common.tool.DateUtils;
import com.newasia.server.controller.form.ChangePassForm;
import com.newasia.server.controller.form.LoginForm;
import com.newasia.server.controller.form.UserForm;
import com.newasia.server.dal.entitys.*;
import com.newasia.server.dal.persistence.LogPhoneCodeMapper;
import com.newasia.server.dal.persistence.UserMapper;
import com.newasia.server.dal.persistence.WxLoginMapper;
import com.newasia.server.service.IUserService;
import com.newasia.server.shiro.EncryptionUtil;
import com.newasia.server.shiro.ShiroUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Slf4j
@Service
public class UserServiceImpl implements IUserService{

    @Autowired(required = false)
    private UserMapper userMapper;
    @Autowired(required = false)
    LogPhoneCodeMapper logPhoneCodeMapper;
    @Autowired(required = false)
    WxLoginMapper wxLoginMapper;

    /**
     *用户登录
     * @author LiChong
     * @date 2020/4/8
     * @param  * @param form
     * @return com.newasia.server.common.result.ResponseData
     */
    @Override
    public ResponseData login(LoginForm form) {
        form.requestCheck();
        User login = new User();
        ResponseData responseData = new ResponseData();
        //进行身份验证
        try{
            //验证身份和登陆
            Subject subject = SecurityUtils.getSubject();
            //验证成功进行登录操作
            subject.login(form.login());
        }catch(WeChatLoginException e){
            return ExceptionUtil.handlerExceptionShiro(responseData,e);
        }catch (IncorrectCredentialsException e) {
            return ExceptionUtil.handlerExceptionShiro(responseData,e);
        }catch (LockedAccountException e) {
            return ExceptionUtil.handlerExceptionShiro(responseData,e);
        }catch (AuthenticationException e) {
            return ExceptionUtil.handlerExceptionShiro(responseData,e);
        }catch (Exception e){
            return ExceptionUtil.handlerExceptionShiro(responseData,e);
        }
        ShiroUtils.getUserInfo().setToken(ShiroUtils.getSession().getId().toString());
        login = ShiroUtils.getUserInfo();
        User user = new User();
        user.setUserName(login.getUserName());
        user.setToken(login.getToken());
        user.setCompany(login.getCompany());
        responseData.setResult(user);
        return responseData;
    }

    /**
     *以名字获取用户信息
     * @author LiChong
     * @date 2020/4/8
     * @param  * @param username
     * @return com.newasia.server.dal.entitys.User
     */
    @Override
    public User selectUserByUsername(String username) {
        User user = userMapper.selectByPrimaryKey(username);
        return user;
    }

    /**
     *注册用户
     * @author LiChong
     * @date 2020/4/8
     * @param  * @param form
     * @return com.newasia.server.common.result.ResponseData
     */
    @Override
    public ResponseData register(UserForm form) {

        ResponseData responseData = new ResponseData();
        //注册
        try {
            CheckHandler.Builder builder = new CheckHandler.Builder();
            builder.addHandler(new UsernameNormCheckHandler() )
                    .addHandler(new UsernameExistCheckHandler())
                    .addHandler(new PasswordCheckHandler())
                    .addHandler(new MobileCheckHandler())
                    .addHandler(new CodeCheckHandler());
            builder.build().doHandler(form);

            User user = new User();
            user.setUserName(form.getUsername());
            user.setPass(EncryptionUtil.md5(form.getPassword()));
            user.setMobile(form.getMobile());
            user.setCompany(form.getCompany());
            user.setAccountType(-1);
            userMapper.insertSelective(user);
        } catch (Exception e) {
            log.error("UserSerivceImpl.register Exception"+e);
            return ExceptionUtil.handlerException4biz(responseData,e);
        }
        /*String openid = request.getParameter("openid");
        if(openid!=null&&!openid.equals("")) {
            HashMap<String, Object> mes= new HashMap<String, Object>();
            User user = userService.getUserByUserName(user_name);
            Long user_id = user.getUserId();
            String loginIp = user.getLoginIp();
            userService.updateWXLogin(user_name, openid,String.valueOf(user_id));
            logService.addLogNew(Long.valueOf(user_id), new Date(),
                    "微信绑定,用户名："+user_name,loginIp, 1, "微信绑定");
        }*/
        return responseData;
    }

    /**
     *验证码发送
     * @author LiChong
     * @date 2020/4/8
     * @param  * @param form
     * @return com.newasia.server.common.result.ResponseData
     */
    @Override
    public ResponseData sendPhoneCode(UserForm form) {
        ResponseData responseData = new ResponseData();
        LogPhoneCode logPhoneCode = new LogPhoneCode();

        try {
            //检测电话号码
            CheckHandler.Builder builder = new CheckHandler.Builder();
            builder.addHandler(new MobileCheckHandler());
            builder.build().doHandler(form);

            String mobile = form.getMobile();
            // 查看验证码表是否有相同记录，有则更新，没有则添加
            LogPhoneCodeExample example = new LogPhoneCodeExample();
            example.createCriteria().andPhoneEqualTo(mobile);
            example.setOrderByClause("expiration desc");
            List<LogPhoneCode> list = logPhoneCodeMapper.selectByExample(example);
            int codeTemp = CodePhoneUtils.creatCodePhone();
            logPhoneCode.setPhone(mobile);
            logPhoneCode.setCode(codeTemp);
            logPhoneCode.setExpiration(DateUtils.getCurrentTime());
            logPhoneCode.setIsverify(false);
            if (list.size()==0) {
                logPhoneCodeMapper.insertSelective(logPhoneCode);
            } else {
                logPhoneCode.setId(list.get(0).getId());
                logPhoneCodeMapper.updateByPrimaryKey(logPhoneCode);
            }
            boolean result = CodePhoneUtils.sendRegistSMS(mobile,codeTemp);
            responseData.setResult(result);
        } catch (Exception e) {
            log.error("UserSerivceImpl.sendPhoneCode Exception"+e);
            return ExceptionUtil.handlerException4biz(responseData,e);
        }
        return responseData;
    }

    /**
     *忘记密码
     * @author LiChong
     * @date 2020/4/8
     * @param  * @param form
     * @return com.newasia.server.common.result.ResponseData
     */
    @Override
    public ResponseData resetPass(UserForm form){
        ResponseData responseData = new ResponseData();
        try {
            CheckHandler.Builder builder = new CheckHandler.Builder();
            builder.addHandler(new MobileCheckHandler())
                    .addHandler(new MobileMatchHandler())
                    .addHandler(new CodeCheckHandler());
            builder.build().doHandler(form);

            String passWord = EncryptionUtil.md5(form.getPassword());
            User user = new User();
            user.setPass(passWord);
            user.setUserName(form.getUsername());
            userMapper.updateByPrimaryKeySelective(user);
        } catch (Exception e) {
            log.error("UserSerivceImpl.resetPass Exception"+e);
            return ExceptionUtil.handlerException4biz(responseData,e);
        }
        return responseData;
    }

    /**
     *变更密码
     * @author LiChong
     * @date 2020/4/8
     * @param  * @param form
     * @return com.newasia.server.common.result.ResponseData
     */
    @Override
    public ResponseData changePass(ChangePassForm form) {
        ResponseData responseData = new ResponseData();
        // 获取请求的手机号
        try {
            String password = EncryptionUtil.md5(form.getNewPassword());
            String username = ShiroUtils.getUserInfo().getUserName();
            User user = new User();
            user.setUserName(username);
            user.setPass(password);
            userMapper.updateByPrimaryKeySelective(user);
        }catch (Exception e){
            log.error("UserSerivceImpl.changePass Exception"+e);
            return ExceptionUtil.handlerException4biz(responseData,e);
        }
        return responseData;
    }

    /**
     *更换手机号码第一步
     * @author LiChong
     * @date 2020/4/8
     * @param  * @param request
     * @return HashMap<String,Object>
     */
    @Override
    public ResponseData updatePhoneFirst(UserForm form) {
        ResponseData responseData = new ResponseData();
        try {
            User user = ShiroUtils.getUserInfo();
            form.setUsername(user.getUserName());
            CheckHandler.Builder builder = new CheckHandler.Builder();
            builder.addHandler(new MobileCheckHandler())
                    .addHandler(new MobileMatchHandler())
                    .addHandler(new CodeCheckHandler());
            builder.build().doHandler(form);
        }catch (Exception e){
            log.error("UserSerivceImpl.updatePhoneFirst Exception"+e);
            ExceptionUtil.handlerException4biz(responseData,e);
        }
        return responseData;
    }

    /**
     *更改手机号码第二步
     * @author LiChong
     * @date 2020/4/8
     * @param  * @param form
     * @return com.newasia.server.common.result.ResponseData
     */
    @Override
    public ResponseData updatePhoneSecond(UserForm form){
        ResponseData responseData = new ResponseData();
        try {
            form.setUsername(ShiroUtils.getUserInfo().getUserName());
            CheckHandler.Builder builder = new CheckHandler.Builder();
            builder.addHandler(new MobileCheckHandler())
                    .addHandler(new CodeCheckHandler());
            builder.build().doHandler(form);

            User user = new User();
            user.setMobile(form.getMobile());
            user.setUserName(form.getUsername());
            userMapper.updateByPrimaryKeySelective(user);
        }catch (Exception e){
            log.error("UserSerivceImpl.updatePhoneSecond Exception"+e);
            ExceptionUtil.handlerException4biz(responseData,e);
        }
        return responseData;
    }

    /**
     *微信绑定
     * @author LiChong
     * @date 2020/4/8
     * @param  * @param form
     * @return com.newasia.server.common.result.ResponseData
     */
    @Override
    public ResponseData bundlingWeChat(LoginForm form) {
        ResponseData responseData = new ResponseData();
        try{
            User user = ShiroUtils.getUserInfo();
            if(CheckObjectIsNullUtils.checkObjIsNull(user)){
                //如果为空，证明未登陆过，重新调用登录接口
                responseData = login(form);
                //如果登录失败，就直接返回账号密码错误
                if(!responseData.isSuccess()){return responseData;}
            }
            //登陆成功，进行微信绑定，同时返回对应的登录信息

        }catch (Exception e){
            log.error("UserSerivceImpl.updatePhoneSecond Exception"+e);
            ExceptionUtil.handlerException4biz(responseData,e);
        }
        return responseData;
    }

    /**
     *微信解绑
     * @author LiChong
     * @date 2020/4/9
     * @param  * @param
     * @return com.newasia.server.common.result.ResponseData
     */
    @Override
    public ResponseData unbundlingWeChat(){
        ResponseData responseData = new ResponseData();
        /*HashMap<String, Object> info =new HashMap<String, Object>();
        String user_name = request.getParameter("user_name");
        HashMap<String, Object> data = userService.getWXLogin(user_name, null);
        String openid = data.get("openid").toString();
        userService.updateWXLogin(null, openid,null);
        info.put("message", "解绑成功");
        info.put("request_status", true);*/
        return responseData;
    }
}
